package fun.codedesign.principle.pattern33.a003.singleton;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

// 单例模式
public abstract class Singleton {
    // 6.枚举天然单例, 用得不多
    public static enum Enum {
        INSTANCE;
    }

    // 1.饿汉加载
    public static class Hungry {
        private static Hungry instance = new Hungry();

        private Hungry() {
        }

        public static Hungry getInstance() {
            return instance;
        }
    }

    // 2.懒加载
    public static class Lazy {
        private static Lazy instance = null;

        private Lazy() {
        }

        public synchronized static Lazy getInstance() {
            if (instance == null) {
                instance = new Lazy();
            }
            return instance;
        }
    }

    // 3.持锁双重检查
    public static class DCK {
        // volatile 1.5版本以前会失效
        private static volatile DCK instance = null;

        private DCK() {
        }

        ;

        public static DCK getInstance() {
            if (null == instance) {
                synchronized (DCK.class) {
                    if (null == instance) {
                        instance = new DCK();
                    }
                }
            }
            return instance;
        }
    }

    // 4.静态内部类的方式：最佳
    public static class Inner {
        private Inner() {
        }

        public static Inner getInstance() {
            return InnerSecond.instance;
        }

        ;

        private static class InnerSecond {
            private static Inner instance = new Inner();
        }
    }

    // 5.ThreadLocal线程私有变量(DCK改进版，更耗资源)
    public static class ThreadPvt {
        private static ThreadLocal<ThreadPvt> local = new ThreadLocal<>();
        private static ThreadPvt instance = null;

        private ThreadPvt() {
        }

        ;

        public static ThreadPvt getInstance() {
            if (local.get() == null) {
                synchronized (ThreadPvt.class) {
                    if (instance == null) {
                        instance = new ThreadPvt();
                    }
                    // 如果已经实例化设置一份到线程私有变量中
                    local.set(instance);
                }
            }
            return instance;
        }
    }

    // 7.容器单例，将实例化的单例注册在map中使用时取出来
    public static class Context {
        private static Map<String, Object> context = new ConcurrentHashMap<>();

        // 模拟注册，Spring一般实现initializingBean接口
        static {
            context.put("hello", Enum.INSTANCE);
            context.put("context", new Context());
        }

        public static Object getBean(String key) {
            if (context.containsKey(key)) {
                return context.get(key);
            } else {
                return null;
            }
        }
    }
}
